一些函数调用的细节问题:
调用前
一个函数的运行期间调用另一个函数时,在运行被调用函数之前,系统需要完成3件事情:
- 将所有的实参、返回地址等信息传递给被调用函数保存;
- 为被调用函数的局部变量分配存储区;
- 将控制转移到被调函数的入口。
调用中
而从被调用函数返回调用函数之前,系统也应完成3件工作:
- 保存被调函数的计算结果;
- 释放被调函数的数据区;
- 依照被调函数保存的返回地址将控制转移到调用函数。当有多个函数构成嵌套调用时,按照后调用先返回的原则。
也就是说,在调用一个函数之前,都会为被调用函数的局部变量分配存储区。
看一下FATFS文件系统中如何做一个能扫两级文件夹的文件扫描。
源代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44u8 mf_scan_files(char * path,u8 recu_level)
{
u8 res;
FILINFO fileinfo;
DIR dir;
char *fn; /* This function is assuming non-Unicode cfg. */
#if _USE_LFN
fileinfo.lfsize = _MAX_LFN * 2 + 1;
fileinfo.lfname = mymalloc(SRAMIN,fileinfo.lfsize);
#endif
res = f_opendir(&dir,(const TCHAR*)path); //?ò??????????
printf("%s\r\n",path);
if (res == FR_OK)
{
while(1)
{
res = f_readdir(&dir, &fileinfo); //????????????????????
if (res != FR_OK || fileinfo.fname[0] == 0) break; //?í?ó??/????????,????
if (fileinfo.fname[0] == '.') continue; //????????????
#if _USE_LFN
fn = *fileinfo.lfname ? fileinfo.lfname : fileinfo.fname;
#else
fn = fileinfo.fname;
#endif
if(recu_level == 1)
{
printf(" |__");
}
else if(recu_level == 2)
{
printf(" | |__");
}
printf("%s\r\n",fn);
if(((fileinfo.fattrib & AM_MASK) == AM_DIR)&&(recu_level == 1))
{
mf_scan_files(fn, 2);
}
}
}
myfree(SRAMIN,fileinfo.lfname);
return res;
}
可以看到,如果是目录下的1级文件,就直接输出|文件名,如果是目录的话,先输出|目录名,然后递归调用了函数本身,传入参数为当前子目录,2;
这样就进入当前子目录(2级目录)的文件扫描,当前子目录的文件扫描,就只扫描名称了,如果再遇到子文件夹,也不再扫描了。
如果的2级目录扫描到头了,if (res != FR_OK || fileinfo.fname[0] == 0) break;
break跳出while循环也就跳出本次的2级目录的scanfiles函数过程。。。。
这时候由于是在1级目录的扫描过程中调用的扫描2级目录,所以函数执行完毕后,又回到1级目录的scanfiles过程,继续往下扫描。
一开始会有疑问,如果2级目录扫描完了,那么&dir中保存的应该是2级目录的目录地址,回到一级目录的扫描函数的话,这个参数就不是1级目录的地址了,怎么能正确执行呢。
看了百度的函数调用过程后,有所明悟。早在函数调用扫描1级目录之前,就分配了本次函数执行所需要的内存变量空间,用来保存本次函数执行过程参数。。。。。
在1级目录调用扫描2级目录之前,,又分配了扫描2级目录所需要的内存变量空间,
所以说,这两次的函数执行,虽然都是同一个函数,但是,内存变量确实分别分配了的,所以2级扫描完成后,返回1级扫描后,所有的参数还是1级扫描的参数,不会有错。